package org.dlsu.hyfilengmt;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.StringTokenizer;

/**
 * Represents the structure of a hybrid transfer rule.
 *
 * @author pckid
 */
public class TransferRule {

	protected String filSide = new String();
	protected String engSide = new String();
	protected int numFilChildren;
	protected int numEngChildren;
	protected String arrFilChildren[];
	protected String arrEngChildren[];
	protected String ruleType = new String(); // "seed" or "comp"
	protected String leftHandSideFil, leftHandSideEng;
	protected String ruleSet; // unique number identifying the ruleset this rule belongs to; 1 ruleset per example learned

	/**
	 * The class constructor.
	 *
	 * @param filSide The Filipino part of this transfer rule
	 * @param engSide The English part of this transfer rule
	 * @param ruleSet The identifier where this transfer rule belongs to
	 */
	public TransferRule(String filSide, String engSide, String ruleSet) {
		this.filSide = filSide = filSide.trim();
		this.engSide = engSide = engSide.trim();
		this.ruleSet = ruleSet;

		if(filSide.contains(":") || engSide.contains(":")) {
			ruleType = "comp";
			if (filSide.contains(":")) {
				StringTokenizer colonTokenizer = new StringTokenizer(filSide, ":");
				if(colonTokenizer.hasMoreElements()) {
					leftHandSideFil = colonTokenizer.nextToken().trim();
				}
				if(colonTokenizer.hasMoreElements()) {
					String tempChildren = colonTokenizer.nextToken().trim();
					StringTokenizer spaceTokenizer = new StringTokenizer(tempChildren, " ");
					numFilChildren = spaceTokenizer.countTokens();
					arrFilChildren = new String[numFilChildren];
					int i = 0;
					while(spaceTokenizer.hasMoreTokens()) {
						arrFilChildren[i] = spaceTokenizer.nextToken().trim();
						i++;
					}
				}
			}

			if (engSide.contains(":")) {
				StringTokenizer colonTokenizer = new StringTokenizer(engSide, ":");
				if(colonTokenizer.hasMoreElements()) {
					leftHandSideEng = colonTokenizer.nextToken().trim();
				}
				if(colonTokenizer.hasMoreElements()) {
					String tempChildren = colonTokenizer.nextToken().trim();
					StringTokenizer spaceTokenizer = new StringTokenizer(tempChildren, " ");
					numEngChildren = spaceTokenizer.countTokens();
					arrEngChildren = new String[numEngChildren];
					int i = 0;
					while(spaceTokenizer.hasMoreTokens()) {
						arrEngChildren[i] = spaceTokenizer.nextToken().trim();
						i++;
					}
				}
			}
		}
		else ruleType = "seed";
	}

	/**
	 * @return
	 */
	public String[] getFilChildren() {
		return arrFilChildren;
	}

	/**
	 * @return
	 */
	public String[] getEngChildren() {
		return arrEngChildren;
	}

	/**
	 * @return
	 */
	public String getFilChildrenString() {
		String tempChildren = new String();
		if (numFilChildren > 0) {
			for(int i = 0; i < arrFilChildren.length; i++) {
				tempChildren = tempChildren + " " + arrFilChildren[i];
			}
			return tempChildren.trim();
		}
		return "";
	}

	/**
	 * @return
	 */
	public String getEngChildrenString() {
		String tempChildren = new String();
		if (numEngChildren > 0) {
			for(int i = 0; i < arrEngChildren.length; i++) {
				tempChildren = tempChildren + " " + arrEngChildren[i];
			}
			return tempChildren.trim();
		}
		return "";
	}

	/**
	 * @return
	 */
	public String getRuleSet() {
		return ruleSet;
	}

	/**
	 * @return
	 */
	public int getNumFilChildren() {
		return arrFilChildren.length;
	}

	/**
	 * @return
	 */
	public int getNumEngChildren() {
		return arrEngChildren.length;
	}

	/**
	 * @return
	 */
	public String getLeftHandSideFil() {
		return leftHandSideFil;
	}

	/**
	 * @return
	 */
	public String getLeftHandSideEng() {
		return leftHandSideEng;
	}

	/**
	 * @return
	 */
	public String getRuleType() {
		return ruleType;
	}

	/**
	 * Prints this transfer rule (to a file) given a PrintWriter object.
	 *
	 * @param out
	 */
	public void printTransferRule(PrintWriter out) {

		out.println("ruleType: " + getRuleType());
		out.println("Fil side = " + filSide + "; number of children " + numFilChildren + ": " + getFilChildrenString() + "; leftHandSide is " + getLeftHandSideFil());
		out.println("Eng side = " + engSide + "; number of children " + numEngChildren + ": " + getEngChildrenString() + "; leftHandSide is " + getLeftHandSideEng());
		out.println();
	}

	/**
	 * Prints this transfer rule on the console window.
	 */
	public void printTransferRule() {

		System.out.println("ruleType: " + getRuleType());
		System.out.println("Fil side = " + filSide + "; number of children " + numFilChildren + ": " + getFilChildrenString() + "; leftHandSide is " + getLeftHandSideFil());
		System.out.println("Eng side = " + engSide + "; number of children " + numEngChildren + ": " + getEngChildrenString() + "; leftHandSide is " + getLeftHandSideEng());
		System.out.println();
	}

	/**
	 * Prints the simplified version of this transfer rule.
	 */
	public void printTransferRuleSimple(){
		System.out.println ("Fil side " + filSide);
		System.out.println ("Eng side " + engSide);
		System.out.println();
	}

	/**
	 *
	 */
	public void sameLeftHandSideAndChildren() {

	}

	public static void loadTransferRules(String parseProduction) {

	}

	/**
	 * Checks the database if this rule already exists in its ruleSet.
	 *
	 * @param con
	 * @return True if rule already exists in leftDB.hybridTransferRules table
	 */
	public boolean ruleExistsInRuleSet(Connection con) {

		String query = new String();

		try {
			query = "SELECT * FROM hybridTransferRules WHERE ruleSet = '" + ruleSet + "' AND filSide = '" + filSide +
					"' AND engSide = '" + engSide + "'";

			Statement stmt =  con.createStatement();
			ResultSet rs = stmt.executeQuery(query);

			if(rs.next()) {
				return true;
			}
		}
		catch(Exception e) {
			System.out.println("Error reading database!");
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * Adds this transfer rule to leftDB.hybridTransferRule table.
	 *
	 * @return True if this rule was added to the table
	 */
	public boolean addRuleToDB() {

		String query = new String();

		try {
			Class.forName("com.mysql.jdbc.Driver");
	        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/leftDB", "root","");
	   		Statement stmt = con.createStatement();

	   		if(ruleType.equalsIgnoreCase("comp"))
	   			query = "INSERT INTO hybridTransferRules ( filSide, engSide, ruleSet, ruleType, leftHandSideFil, " +
	   					"filChildren, leftHandSideEng, engChildren ) VALUES ( '" + filSide + "', '" + engSide + "', '" +
	   					ruleSet + "', '" + ruleType + "', '" + leftHandSideFil + "', '" + getFilChildrenString() + "', '" + leftHandSideEng + "', '" +
	   					getEngChildrenString() + "' )";
	   		else query = "INSERT INTO hybridTransferRules ( filSide, engSide, ruleSet, ruleType ) VALUES ( '" + filSide + "', '" + engSide + "', '" +
						ruleSet + "', '" + ruleType + "' )";

	   		System.out.println("QUERY is " + query);

	   		int result=0;

	   		if (!ruleExistsInRuleSet(con))
	   			result = stmt.executeUpdate(query);

	   		con.close();
	   		if(result == 1)
	   			return true;
	   		return false;
	   	}

		catch(Exception e) {
	   		System.out.println("Connection to database failed!");
	   		e.printStackTrace();
			return false;
		}
	}
}
